package com.rongji.dfish.demo.editor.service.uiadaptor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.rongji.dfish.base.Utils;
import com.rongji.dfish.demo.constant.DemoConstants;
import com.rongji.dfish.demo.entity.DfishViewNode;
import com.rongji.dfish.ui.AbstractWidget;
import com.rongji.dfish.ui.Command;
import com.rongji.dfish.ui.DataContainer;
import com.rongji.dfish.ui.EventTarget;
import com.rongji.dfish.ui.HasId;
import com.rongji.dfish.ui.HiddenContainer;
import com.rongji.dfish.ui.PubHolder;
import com.rongji.dfish.ui.Widget;
import com.rongji.dfish.ui.command.AddCommand;
import com.rongji.dfish.ui.command.ConfirmCommand;
import com.rongji.dfish.ui.command.DialogCommand;
import com.rongji.dfish.ui.command.MenuCommand;
import com.rongji.dfish.ui.command.ReplaceCommand;
import com.rongji.dfish.ui.form.AbstractBox;
import com.rongji.dfish.ui.form.AbstractBoxgroup;
import com.rongji.dfish.ui.form.AbstractFormElement;
import com.rongji.dfish.ui.form.AbstractUpload;
import com.rongji.dfish.ui.form.Checkbox;
import com.rongji.dfish.ui.form.DatePicker;
import com.rongji.dfish.ui.form.Hidden;
import com.rongji.dfish.ui.form.Period;
import com.rongji.dfish.ui.form.Pickbox;
import com.rongji.dfish.ui.form.Radio;
import com.rongji.dfish.ui.form.Radiogroup;
import com.rongji.dfish.ui.form.Spinner;
import com.rongji.dfish.ui.form.Text;
import com.rongji.dfish.ui.form.Textarea;
import com.rongji.dfish.ui.form.UploadButton;
import com.rongji.dfish.ui.form.Validatable;
import com.rongji.dfish.ui.form.Validate;
import com.rongji.dfish.ui.form.Xbox;
import com.rongji.dfish.ui.helper.FlexGrid;
import com.rongji.dfish.ui.helper.FormPanel;
import com.rongji.dfish.ui.helper.GridLayoutFormPanel;
import com.rongji.dfish.ui.helper.GridPanel;
import com.rongji.dfish.ui.helper.StackPanel;
import com.rongji.dfish.ui.helper.TabPanel;
import com.rongji.dfish.ui.helper.VerticalGroup;
import com.rongji.dfish.ui.layout.AbstractLayout;
import com.rongji.dfish.ui.layout.ButtonBar;
import com.rongji.dfish.ui.layout.FieldsetLayout;
import com.rongji.dfish.ui.layout.GridLayout;
import com.rongji.dfish.ui.layout.HorizontalLayout;
import com.rongji.dfish.ui.layout.View;
import com.rongji.dfish.ui.layout.grid.GridColumn;
import com.rongji.dfish.ui.layout.grid.Thead;
import com.rongji.dfish.ui.layout.grid.Tr;
import com.rongji.dfish.ui.widget.Button;
import com.rongji.dfish.ui.widget.DialogTemplate;
import com.rongji.dfish.ui.widget.Img;
import com.rongji.dfish.ui.widget.Leaf;
import com.rongji.dfish.ui.widget.Split;
import com.rongji.dfish.ui.widget.SubmitButton;

public class ViewBuilder {
	ViewBuilder(ComponentInfo compInfo){
//		init(compInfo);
	}
	/**
	 * 根据视图节点列表组装成预览视图组件
	 * @param viewNodes 视图节点列表
	 * @return 预览视图组件
	 */
	public Widget<?> getWidget(List<DfishViewNode> viewNodes,boolean perview) {
		if (Utils.isEmpty(viewNodes)) {
			return null;
		}
		Map<String, List<DfishViewNode>> mapping = new HashMap<String, List<DfishViewNode>>();
		for (DfishViewNode viewNode : viewNodes) {
			List<DfishViewNode> nodes = mapping.get(viewNode.getNodeParent());
			if (nodes == null) {
				nodes = new ArrayList<DfishViewNode>();
				if (Utils.isEmpty(viewNode.getNodeParent())) {
					viewNode.setNodeParent(DemoConstants.ID_ROOT);
				}
				mapping.put(viewNode.getNodeParent(), nodes);
			}
			nodes.add(viewNode);
		}
		List<DfishViewNode> rootNodes = mapping.get(DemoConstants.ID_ROOT);
		List<Object> nodes = new ArrayList<Object>();
		if(rootNodes!=null){
			for (DfishViewNode viewNode : rootNodes) {
				TypeAdaptor adaptor = AdaptorManager.getInstance().getCompInfo().getAdaptor(viewNode.getNodeType());
				if (adaptor == null) {
					continue;
				}
				Object instance = adaptor.newInstance(AdaptorManager.parseData(viewNode), viewNode);
				nodes.add(instance);
				//如果是根节点的话，自身要初始化属性
				if(DemoConstants.ID_ROOT.equals(viewNode.getNodeParent())){
					ComponentData data = AdaptorManager.parseData(viewNode);
					fillProps(instance, data,adaptor);
				}
				fillSubNodeCascade(instance, viewNode.getNodeId(), mapping,perview);
			}
		}
		// FIXME 这里返回的可能不止一个,目前假定只有一个,且根是View
		if(nodes.size()>0){
			return (Widget<?>) nodes.get(0);
		}
		return null;
	}
	/**
	 * 填充预览的下级节点组件
	 * @param parent 父组件对象
	 * @param pId 父节点编号
	 * @param mapping 父编号对应其子节点的映射
	 */
	private void fillSubNodeCascade(Object parent, String pId, Map<String, List<DfishViewNode>> mapping,boolean preview) {
		List<DfishViewNode> subNodes = mapping.get(pId);
		if (subNodes != null) {
			for (DfishViewNode selfNode : subNodes) {
				TypeAdaptor adaptor =AdaptorManager.getInstance().getCompInfo().getAdaptor(selfNode.getNodeType());
				if (adaptor == null) {
					continue;
				}
				Object self = buildInstance(parent, selfNode,preview,adaptor);
				fillSubNodeCascade(self, selfNode.getNodeId(), mapping,preview);
			}
		}
	}
	public final Object buildInstance(Object parent, DfishViewNode viewNode,boolean preview,TypeAdaptor adaptor) {
    	ComponentData data = AdaptorManager.parseData(viewNode);
    	// 创建原型对象
    	Object instance = adaptor.newInstance(data, parent);
    	// 初始化原型对象
    	fillProps(instance, data,adaptor);
    	// 将原型对象填充到父对象中去
    	append2Parent(parent, instance, data);
    	// 添加右键动作命令
    	if (preview&&instance instanceof EventTarget<?>) {
    		// FIXME 当原本视图有右键动作时该如何处理?暂时不考虑右键动作
    		((EventTarget<?>) instance).setOn("contextmenu", "editor.file.nodeMenu(this, '" + viewNode.getNodeId() + "', '" + viewNode.getViewId() + "');");
    	}
    	if (preview&&instance instanceof Widget<?>) {
    		// FIXME 当原本视图有GID时该如何处理?暂时不考虑关联操作
    		((Widget<?>) instance).setGid(viewNode.getNodeId());
    	}
	    return instance;
    }
	   private void fillProps(Object instance, ComponentData data,TypeAdaptor adaptor) {
		   if (instance == null || data == null) {
				return;
			}
		    //判断是否文件加载的组件
			adaptor= AdaptorManager.getInstance().getCompInfo().getComponentDefine((ComponentTypeAdaptor) adaptor);
			Map<String, PropertyDefine> propDefines = adaptor.getDefinePropMap();
			
			fillSelfProps(instance, data.getProps(), propDefines);
			if(instance instanceof HiddenContainer){
				fillHiddensProps((HiddenContainer<?>)instance,data.getHiddensProps());
			}
			if(instance instanceof DataContainer){
				fillDataProps((DataContainer<?>)instance,data.getDataProps());
			}
			if(instance instanceof EventTarget){
				fillEventProps((EventTarget<?>)instance,data.getEventProps());
			}

	}
	/**
     * 填充预览的下级节点
     * @param parent 父原型实例
     * @param self 自身原型实例
     * @param data 组件数据
     */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	protected void append2Parent(Object parent, Object self, ComponentData data) {
		if (parent == null || self == null) {
			return;
		}
		if (parent instanceof View) {
			View cast = (View) parent;
			if (self instanceof DialogTemplate){
				cast.addTemplate(((DialogTemplate) self).getId(), (DialogTemplate)self);
				// FIXME View.addViewTemplate...
			}else if (self instanceof Widget) {
				cast.add((Widget<?>) self);
			} else if (self instanceof Command) {
				Map<String, String> parentProps = data.getParentProps();
				if(parentProps!=null){
					String id = parentProps.get("id");
					cast.addCommand(id,(Command<?>) self);//VIEW应该提供一种设置ID的办法
				}
			}  
		} else if (parent instanceof Command) {
			if (parent instanceof ReplaceCommand) {
				ReplaceCommand cast = (ReplaceCommand) parent;
				cast.setNode((Widget<?>) self);
			} else if (parent instanceof AddCommand) {
				AddCommand cast = (AddCommand) parent;
				cast.add((Widget<?>) self);
			} else if (parent instanceof MenuCommand) {
				MenuCommand cast = (MenuCommand) parent;
				if (self instanceof Button) {
					cast.add((Button) self);
				} else if (self instanceof Split) {
					cast.add((Split) self);
				} else if (self instanceof SubmitButton) {
					cast.add((SubmitButton) self);
				}
			} else if (parent instanceof ConfirmCommand) {
				ConfirmCommand cast = (ConfirmCommand) parent;
				if("<yes>".equals(data.getMode())){
					cast.setYes((Command)self);
				}else if("<no>".equals(data.getMode())){
					cast.setNo((Command)self);
				}
			}
		} else if (parent instanceof GridLayout) {
			if (self instanceof GridColumn) {
				GridLayout cast = (GridLayout) parent;
				cast.addColumn((GridColumn) self);
			}else  if (self instanceof Tr){
				GridLayout cast = (GridLayout) parent;
				Tr selfCast=(Tr)self;
				if("<pub>".equals(data.getMode())){
					cast.setPub(selfCast);
				}else{
					cast.add(selfCast);
				}
			}else if(self instanceof Thead){
				GridLayout cast = (GridLayout) parent;
				cast.setThead((Thead) self);
			}else if(self instanceof Widget<?>){
				GridLayout cast = (GridLayout) parent;
				Widget<?> selfCast=(Widget<?>)self;
				Map<String, String> parentProps = data.getParentProps();
				if(parentProps!=null){
					Integer fromRow = AdaptorManager.parseInt(parentProps.get("fromRow"));
					Integer fromColumn = AdaptorManager.parseInt(parentProps.get("fromColumn"));
					Integer toRow = AdaptorManager.parseInt(parentProps.get("toRow"));
					Integer toColumn = AdaptorManager.parseInt(parentProps.get("toColumn"));
					cast.add(fromRow, fromColumn, toRow, toColumn, selfCast);
				}else{
					cast.add(0, 0, selfCast);
				}
				
			}
		}else if (parent instanceof GridLayoutFormPanel) {
			GridLayoutFormPanel cast = (GridLayoutFormPanel) parent;
			Map<String, String> parentProps = data.getParentProps();
			Widget<?> selfCast=(Widget<?>)self;
			if(parentProps!=null){
				Integer fromRow = AdaptorManager.parseInt(parentProps.get("fromRow"));
				Integer fromColumn = AdaptorManager.parseInt(parentProps.get("fromColumn"));
				Integer toRow = AdaptorManager.parseInt(parentProps.get("toRow"));
				Integer toColumn = AdaptorManager.parseInt(parentProps.get("toColumn"));
				cast.add(fromRow, fromColumn, toRow, toColumn, selfCast);
			}else{
				cast.add(0, 0, selfCast);
			}
		}else if (parent instanceof GridPanel) {
			if (self instanceof GridColumn) {
				GridPanel cast = (GridPanel) parent;
				cast.addColumn((GridColumn) self);
			} if (self instanceof Tr){
				GridPanel cast = (GridPanel) parent;
				Tr selfCast=(Tr)self;
				if("<pub>".equals(data.getMode())){
					cast.setPub(selfCast);
				}
			}
		}else if (parent instanceof FlexGrid) {
			FlexGrid cast = (FlexGrid) parent;
			Map<String, String> parentProps = data.getParentProps();
			Widget<?> selfCast=(Widget<?>)self;
			if(parentProps!=null){
				Integer occupy = AdaptorManager.parseInt(parentProps.get("occupy"));
				if(occupy==null){
					cast.add(selfCast);
				}else{
					cast.add(selfCast,occupy);
				}
			}else{
				cast.add(selfCast);
			}
		}else if (parent instanceof StackPanel||parent instanceof TabPanel) {
			if(self instanceof Widget){
				Map<String, String> parentProps = data.getParentProps();
				String title=parentProps.get("title");
				String icon=parentProps.get("icon");
				if (parent instanceof StackPanel){
					StackPanel cast = (StackPanel) parent;
					cast.addSubWidget(icon, title, (Widget<?>) self);
				}else{
					TabPanel cast = (TabPanel) parent;
					cast.addSubWidget(icon, title, (Widget<?>) self);
				}
			}
		}else if (parent instanceof FormPanel) {
			FormPanel cast = (FormPanel) parent;
			if(self instanceof Widget){
				cast.add((Widget<?>) self);
			}else if(self instanceof Hidden){
				Hidden hidden=( Hidden)self;
				cast.addHidden(hidden.getName(), hidden.getValue());
			}
		}else if (parent instanceof Period) {
			if(self instanceof DatePicker){
				Period cast = (Period) parent;
				if("<begin>".equals(data.getMode())){
					cast.setBegin((DatePicker)self);
				}else if("<end>".equals(data.getMode())){
					cast.setEnd((DatePicker)self);
				}
			}
		}else if (parent instanceof AbstractLayout) {
			AbstractLayout cast = (AbstractLayout) parent;
			HasId selfCast=(HasId)self;
			if("<pub>".equals(data.getMode())){
				PubHolder<?,Object> holder=(PubHolder<?,Object>) parent;
				holder.setPub(selfCast);
			}else if("<box>".equals(data.getMode())){
				AbstractBox<?> box=(AbstractBox<?>)self;
				if(parent instanceof GridColumn){
					((GridColumn) parent).setBox(box);
				}else if(parent instanceof FieldsetLayout){
					((FieldsetLayout) parent).setBox(box);
				}else if(parent instanceof Img){
					((Img) parent).setBox(box);
				}else if(parent instanceof Leaf){
					((Leaf) parent).setBox(box);
				}
			}else if("<split>".equals(data.getMode())){
				Split split=(Split)self;
				if(parent instanceof ButtonBar){
					((ButtonBar) parent).setSplit(split);
				}
			}else if(self instanceof Widget){
				cast.add((Widget<?>) self);
			}
		}else if (parent instanceof AbstractBoxgroup){
			AbstractBoxgroup cast=(AbstractBoxgroup) parent;
			if(self instanceof Widget){
				if("[target]".equals(data.getMode())){
					List<Widget<?>> targets=cast.getTargets();
					if(Utils.isEmpty(targets)){
						targets=new ArrayList<Widget<?>>();
					}
					cast.addTarget((Widget<?>) self);
				}else{
					cast.add((AbstractBox) self);
				}
			}
		}else if (parent instanceof AbstractUpload) {
			AbstractUpload cast=(AbstractUpload) parent;
			if(self instanceof UploadButton){
				cast.addUpload_button((UploadButton)self);
			}
		}else if (parent instanceof Pickbox) {
			if(self instanceof DialogCommand){
				DialogCommand selfCast=(DialogCommand)self;
				Pickbox cast=(Pickbox) parent;
				cast.setPicker(selfCast);
			}
		}else if (parent instanceof Validatable) {
			if(self instanceof Validate){
				Validatable cast = (Validatable) parent;
				cast.addValidate((Validate) self);
				//FIXME 可能是带名字的
			}
		}
	}
//	/**
//	 * 设置对象的某个属性值
//	 * 使用此方法设置属性值，这个属性必须有对应setter方法
//	 * @param obj 对象
//	 * @param propName 属性名称
//	 * @param value 属性值
//	 */
//	public static void setPropValue(Object obj, String propName, Object value) {
//		if (obj == null || value == null || Utils.isEmpty(propName)) {
//			return;
//		}
//		String methodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
//		setValue(obj, methodName, value);
//	}
	
	/**
	 * 根据方法名和方法参数调用此对象的方法
	 * @param obj 对象
	 * @param methodName 方法名
	 * @param value 方法参数
	 */
	public static void setValue(Object obj, String propName, Object value) {
		if (obj == null || value == null || Utils.isEmpty(propName)) {
			return;
		}
		String methodName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1);
		Class<?> clz=value.getClass();
		Method method=null;
		//FIXME 这里找方法的思路比较混乱，要根据方法名和参数找个一个最合适的方法，可能不需要while(true)循环往上找。
//			 //GridPanel设置GridData的时候是Collection类型的，value.getClass()得到的是ArrayList类型
//				if(Collection.class.isAssignableFrom(clz)){
//					clz=Collection.class;
//				}else if(Integer.class.isAssignableFrom(clz)){
//			//GridColumn设置dataColumnIndex的时候是int类型，value.getClass()得到的是Integer类型
//					clz=int.class;
//				}
		
//		while(true){
//			 try {
//				 method = obj.getClass().getMethod(methodName, clz);
//			} catch (SecurityException e) {
//			} catch (NoSuchMethodException e) {
//				e.printStackTrace();
//			}
//			if(clz==Object.class){
//				break;
//			}
//			clz=clz.getSuperclass();
//		}
		 try {
			 method = obj.getClass().getMethod(methodName, clz);
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			//如果找不到，查询这个方法下面的所有方法,可能会耗性能，后面需要改进
			Method[] methods = obj.getClass().getMethods();
			for (Method m : methods) {
				if(methodName.equals(m.getName())&&(m.getParameterTypes().length==1)){
					method=m;
					break;
				}
			}
			if(method==null){
				Logger.getLogger(ViewBuilder.class).error("无法找到方法名为："+methodName+"，类型为："+clz.getName()+"对应的方法");
			}
		}
		try {
			 if(method!=null){
				 method.invoke(obj, value);
			 }
        } catch (Exception e) {
	        e.printStackTrace();
        } 
	}
	/**
	 * 设置属性 //FIXME data event hiddens
	 * @param instance
	 * @param props
	 * @param propDefines
	 */
	private static void fillSelfProps(Object instance, Map<String, String> props, Map<String, PropertyDefine> propDefines) {
		if (Utils.isEmpty(props)) {
			return;
		}
		for (Map.Entry<String, String> entry : props.entrySet()) {
			String propName = entry.getKey();
			PropertyDefine propDef = propDefines.get(propName);
			if (propDef == null ) {
				continue;
			}
			if("id".equals(propDef.getName())){//特殊属性进行屏蔽
				if(entry.getValue()!=null&&entry.getValue().startsWith("<")){
					continue;
				}
			}
			setValue(instance, propName, parseValue(propName, entry.getValue(), propDefines));
		}
	}
	private static void fillDataProps(DataContainer<?> instance, Map<String, String> props) {
		if (Utils.isEmpty(props)) {
			return;
		}
		for (Map.Entry<String, String> entry : props.entrySet()) {
			instance.setData(entry.getKey(), entry.getValue());
		}
	}
	private static void fillEventProps(EventTarget<?> instance, Map<String, String> props) {
		if (Utils.isEmpty(props)) {
			return;
		}
		for (Map.Entry<String, String> entry : props.entrySet()) {
			instance.setOn(entry.getKey(), entry.getValue());
		}
	}
	private static void fillHiddensProps(HiddenContainer<?> instance, Map<String, String> props) {
		if (Utils.isEmpty(props)) {
			return;
		}
		for (Map.Entry<String, String> entry : props.entrySet()) {
			instance.addHidden(entry.getKey(), entry.getValue());
		}
	}
	
	

//	public static final Object ELEM_TYPE_DATEPICKER=new Object();
	public static final Object ELEM_TYPE_STRING=new Object();
	public static final Object ELEM_TYPE_INTEGER=new Object();
	public static final Object ELEM_TYPE_NUMBER=new Object();
	public static final Object ELEM_TYPE_INT=new Object();
	public static final Object ELEM_TYPE_ID=new Object();
	public static final Object ELEM_TYPE_TEXT=new Object();
	static final HashMap<String, Object> PROP_TYPE_MAP=new HashMap<String, Object>();
	static final HashMap<Object, FormElementBuilder> FORM_ELEMENT_BUILDERS=new HashMap<Object, FormElementBuilder>();
	static{
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_INTEGER, new IntegerBuilder(ELEM_TYPE_INTEGER));
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_NUMBER, new NumberBuilder(ELEM_TYPE_NUMBER));
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_INT, new IntegerBuilder(ELEM_TYPE_INT));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_BOOLEAN, new OptionsBuilder(ComponentInfo.ELEM_TYPE_BOOLEAN));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_ALIGN, new OptionsBuilder(ComponentInfo.ELEM_TYPE_ALIGN));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_VALIGN, new OptionsBuilder(ComponentInfo.ELEM_TYPE_VALIGN));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_SCROLLCLASS, new OptionsBuilder(ComponentInfo.ELEM_TYPE_SCROLLCLASS));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_DATE_FORMAT, new OptionsBuilder(ComponentInfo.ELEM_TYPE_DATE_FORMAT));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_PAGE, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_PAGE));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_CALENDAR, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_CALENDAR));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_BOOLEAN_NOT_NULL, new BooleanNotNullBuilder(ComponentInfo.ELEM_TYPE_BOOLEAN_NOT_NULL));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_TRIPLEBOX, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_TRIPLEBOX));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_GRIDLAYOUT, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_GRIDLAYOUT));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_GRIDCOLUMN, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_GRIDCOLUMN));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_PATTERN, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_PATTERN));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_DIALOGWIDTH, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_DIALOGWIDTH));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_DIALOGHEIGHT, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_DIALOGHEIGHT));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_SUBMITCOMMAND, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_SUBMITCOMMAND));
		FORM_ELEMENT_BUILDERS.put(ComponentInfo.ELEM_TYPE_TYPE_BUTTONBAR, new OptionsBuilder(ComponentInfo.ELEM_TYPE_TYPE_BUTTONBAR));
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_TEXT, new TextareaBuilder(ELEM_TYPE_TEXT));
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_ID, new IDBuilder(ELEM_TYPE_ID));
		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_STRING, new OtherBuilder(ELEM_TYPE_STRING));
//		FORM_ELEMENT_BUILDERS.put(ELEM_TYPE_DATEPICKER, new OptionsBuilder(ELEM_TYPE_DATEPICKER));

			
		initPropType("", ELEM_TYPE_STRING);//默认
		initPropType("Boolean", ComponentInfo.ELEM_TYPE_BOOLEAN);
		initPropType("boolean", ComponentInfo.ELEM_TYPE_BOOLEAN_NOT_NULL);
		initPropType("Integer", ELEM_TYPE_INTEGER);
		initPropType("int", ELEM_TYPE_INT);
		initPropType("Number", ELEM_TYPE_NUMBER);
		initPropType("Object", ELEM_TYPE_STRING);
		initPropType("String", ELEM_TYPE_STRING);
		initPropType("String", "align", ComponentInfo.ELEM_TYPE_ALIGN);
		initPropType("String", "face", ComponentInfo.ELEM_TYPE_TYPE_GRIDLAYOUT);
		initPropType("String", "format", "DatePicker", ComponentInfo.ELEM_TYPE_DATE_FORMAT);
		initPropType("String", "format", "MuldatePicker", ComponentInfo.ELEM_TYPE_DATE_FORMAT);
		initPropType("String", "height", "DialogTemplate", ComponentInfo.ELEM_TYPE_TYPE_DIALOGHEIGHT);
		initPropType("String", "height", "DialogCommand", ComponentInfo.ELEM_TYPE_TYPE_DIALOGHEIGHT);
		initPropType("String", "width", "DialogTemplate", ComponentInfo.ELEM_TYPE_TYPE_DIALOGWIDTH);
		initPropType("String", "width", "DialogCommand", ComponentInfo.ELEM_TYPE_TYPE_DIALOGWIDTH);
		initPropType("String", "id", ELEM_TYPE_ID);
		initPropType("String", "key", "Event",ELEM_TYPE_TEXT);
		initPropType("String", "name", ELEM_TYPE_ID);
		initPropType("String", "pattern", "Validate", ComponentInfo.ELEM_TYPE_TYPE_PATTERN);
		initPropType("String", "scrollClass", ComponentInfo.ELEM_TYPE_SCROLLCLASS);
		initPropType("String", "text", ELEM_TYPE_TEXT);
		initPropType("String", "type", "CalendarPanel", ComponentInfo.ELEM_TYPE_TYPE_CALENDAR);
		initPropType("String", "type", "PagePanel", ComponentInfo.ELEM_TYPE_TYPE_PAGE);
		initPropType("String", "validateeffect", ComponentInfo.ELEM_TYPE_TYPE_SUBMITCOMMAND);
		initPropType("String", "valign", ComponentInfo.ELEM_TYPE_VALIGN);
		initPropType("String", "dir", "ButtonBar", ComponentInfo.ELEM_TYPE_TYPE_BUTTONBAR);
//		initPropType("DatePicker", "begin", ELEM_TYPE_DATEPICKER);
//		initPropType("DatePicker", "end", ELEM_TYPE_DATEPICKER);
		initPropType("String", "value", "Textarea", ELEM_TYPE_TEXT);
		initPropType("Object", "value", "Triplebox", ComponentInfo.ELEM_TYPE_TYPE_TRIPLEBOX);
		
	}
	

		
	private static final void initPropType(String propType,Object elemType){
		PROP_TYPE_MAP.put(propType, elemType);
	}
	private static final void initPropType(String propType,String propName,Object elemType){
		if(propName!=null&&propName.equals("")){
			initPropType(propType,elemType);
		}else{
			initPropType(propType+"("+propName+")",elemType);
		}
	}
	private static final void initPropType(String propType,String propName,String ctrType,Object elemType){
		if(propName!=null&&propName.equals("")){
			initPropType(propType,elemType);
		}else if(ctrType!=null&&ctrType.equals("")){
			initPropType(propType+"("+propName+")",elemType);
		}else{
			initPropType(propType+"("+propName+"_"+ctrType+")",elemType);
		}
	}
	/**
	 * 识别属性使用哪个控件进行编辑。
	 * @param propType String 属性类型
	 * @param propName String 属性名
	 * @param ctrType String 属性所在组件类型
	 * @return 控件类型
	 */
	public Object getPropEditType(String propType,String propName,String ctrType){
		String key=propType+"("+propName+"_"+ctrType+")";
		Object result=PROP_TYPE_MAP.get(key);
		if(result!=null){
			return result;
		}
		key=propType+"("+propName+")";
		result=PROP_TYPE_MAP.get(key);
		if(result!=null){
			return result;
		}
		key=propType;
		result=PROP_TYPE_MAP.get(key);
		if(result!=null){
			return result;
		}
		result=PROP_TYPE_MAP.get("");

		return result;
	}

	/**
	 * 在组件属性编辑页面上，使用该方法决定每个类型的属性使用什么控件进行编辑
	 * @param propDef 属性定义信息
	 * @param value 当前属性的值。
	 * @param ctrType 视图节点的控件类型。
	 * @return AbstractFormElement
	 */
	public  AbstractWidget<?> getFormElement(PropertyDefine propDef, Object value, String ctrType) {
		String name=propDef.getName();
		Object type=getPropEditType(propDef.getType(),name,ctrType);
		FormElementBuilder builder=FORM_ELEMENT_BUILDERS.get(type);
		if(builder==null){
			builder=new OtherBuilder(type);
			FORM_ELEMENT_BUILDERS.put(type, builder);
		}
		//改为使用builder的模式，
		//1使这里代码不会无限累计太长。
		//2 防止过多的if else判断降低性能
		AbstractWidget<?> formEl=null;
		if((type==ComponentInfo.ELEM_TYPE_TYPE_DIALOGWIDTH||type==ComponentInfo.ELEM_TYPE_TYPE_DIALOGHEIGHT)&&
				("width".equals(name)||"height".equals(name))){
			 formEl = builder.buildLayoutElement(name,value,ctrType);
		}else{
			 formEl = builder.buildFormElement(name,value,ctrType);
			 ((AbstractFormElement<?, ?>) formEl).setRequired(propDef.getRequired());
		}
		
		return formEl;
	}
	@SuppressWarnings("rawtypes")
	public static Object toArg(String argStr, Class clz) {
		if (clz == String.class) {//因为大部分属性应该都是String型优先做这个判断将提高性能，无这个判断并不会影响结果。
			return argStr;
		}
		if (argStr == null || argStr.equals("")) {
			return null;
		}
		if (clz == Integer.class || clz == int.class) {
			return new Integer(argStr);
		} else if (clz == Long.class || clz == long.class) {
			return new Long(argStr);
		} else if (clz == Number.class ) {
			return new Double(argStr);
		} else if (clz == Boolean.class || clz == boolean.class) {
			return "1".equals(argStr);
		} else if (clz.isArray()){
			Object[] opt=new Gson().fromJson(argStr, Object[].class);
			return opt;
			// FIXME 可能有其他类型如Date option Object
		}else if (Collection.class.isAssignableFrom(clz)){
			//如果是list和Collection都走这里
			if(argStr.startsWith("[[")){
				
				Collection<Object[]> opt=new Gson().fromJson(argStr, new TypeToken<Collection<Object[]>>(){}.getType());
				return opt;
			}else{
				Collection<Object> opt=new Gson().fromJson(argStr, new TypeToken<Collection<Object>>(){}.getType());
				return opt;
			}
		}else if(clz== Split.class){
			return new Split().setWidth(argStr);
		}else if(clz== Object.class){
			return argStr;
		}
		Logger.getLogger(ViewBuilder.class).error("无法解析 "+clz.getName()+" ="+argStr);
		return argStr;
	}
	/**
	 * 转
	 * @param propName
	 * @param propValue
	 * @param propDefines
	 * @return
	 */
	public static Object parseValue(String propName, String propValue, Map<String, PropertyDefine> propDefines) {
		PropertyDefine propDef = propDefines.get(propName);
		Object parseValue = propValue;
		String propType = "";
		if (propDef == null) {
			return parseValue;
		}
		propType = propDef.getType();
		try {
			return toArg(propValue,BeanExtUtil.convert(propType));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	private static interface FormElementBuilder{
		AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType);
		AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType);
		Object getType();
	}
	private static abstract class AbstractFormElementBuilder implements FormElementBuilder{
		protected Object type;
		AbstractFormElementBuilder(Object type){
			this.type=type;
		}
		public Object getType(){
			return type;
		}
		public String getCname(String name,String ctrType){
			return AdaptorManager.getInstance().getCompInfo().getPropName(name, ctrType);
		}
		public String getPlaceholder(String name,String ctrType){
			return AdaptorManager.getInstance().getCompInfo().getPropTip(name, ctrType);
		}
	}
	private static class OptionsBuilder extends AbstractFormElementBuilder{
		OptionsBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
//			if(type==ELEM_TYPE_DATEPICKER){
//				return new DatePicker(name, getCname(name, ctrType), value, DatePicker.DATE_TIME_FULL);
//			}
			List<Object[]>options=AdaptorManager.getInstance().getCompInfo().getOptions(type);
			if(options==null){
				//不该发生
				throw new RuntimeException("不可识别的类型 "+type);
			}else	if(options.size()>5){
				return new Xbox(name, getCname(name, ctrType), value, options);
			}else{
				return new Radiogroup(name, getCname(name, ctrType), (String) value, options);
			}
		}
		public AbstractLayout<?,?>  buildLayoutElement(String name,Object value,String ctrType){
			List<Object[]>options=AdaptorManager.getInstance().getCompInfo().getOptions(type);
			if(options==null){
				//不该发生
				throw new RuntimeException("不可识别的类型 "+type);
//			}else	if(options.size()>=5){
//				return new XBox(name, getCname(name, ctrType), value, options);
			}else{
				VerticalGroup verticalGroup=new VerticalGroup(name+"verticalPanel");
				verticalGroup.setLabel(getCname(name, ctrType));
				Radiogroup radiogroup=new Radiogroup(name, getCname(name, ctrType), String.valueOf(value), options);
				verticalGroup.add(radiogroup);
				boolean isChecked=false;
				for(Object[] option:options){
					if(!String.valueOf(value).equals(String.valueOf(option[0]))){
						isChecked=true;
					}else {
						isChecked =false;
						break;
					}
				}
				Radio r1=new Radio(name, "", isChecked, "", "其他");
				Number v = null;
				try {
					v = Integer.parseInt(String.valueOf(value));
				} catch (Exception e) { }
				Spinner sp1 =  new Spinner("target"+name,"值",isChecked?v:null,0,9999999,1).setId(name+"sp").setWidth("100");
				r1.setTarget(sp1.getId());
				HorizontalLayout horizontalLayout=new HorizontalLayout("horizontalLayout");
				horizontalLayout.add(r1, "50");
				horizontalLayout.add(sp1);
				verticalGroup.add(horizontalLayout);
				return verticalGroup;
			}
		}
	}
	private static class IntegerBuilder extends AbstractFormElementBuilder{
		IntegerBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			Number v = null;
			try {
				v = Integer.parseInt(String.valueOf(value));
		    } catch (Exception e) { }
			return new Spinner(name, getCname(name, ctrType), v, 0, 99999999, 1);
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}
	private static class NumberBuilder extends AbstractFormElementBuilder{
		NumberBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			Number v = null;
			try {
				v = Double.parseDouble(String.valueOf(value));
		    } catch (Exception e) { }
			return new Spinner(name, getCname(name, ctrType), v, 0.0, 99999999.0, 1.0);
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}
	private static class BooleanNotNullBuilder extends AbstractFormElementBuilder{
		BooleanNotNullBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			return  new Checkbox(name, getCname(name, ctrType),"1".equals(value),"1",null);
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}
	private static class TextareaBuilder extends AbstractFormElementBuilder{
		TextareaBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			return  new Textarea(name, getCname(name, ctrType), (String) value).setHeight("80").setPlaceholder(getPlaceholder(name, ctrType));
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}
	private static class IDBuilder extends AbstractFormElementBuilder{
		IDBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			AbstractFormElement<?,?>formEl = new Text(name, getCname(name, ctrType), (String) value).setPlaceholder(getPlaceholder(name, ctrType));
			String idValue=(String)value;
			if((idValue!=null) &&idValue.startsWith("<")){
				formEl.setReadonly(true);
			}else{
				formEl.addValidate(Validate.pattern("/^\\w+$/g"));
			}
			return  formEl;//new Textarea(name, getCname(name, ctrType), (String) value).setHeight("80");
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}
	private static class OtherBuilder extends AbstractFormElementBuilder{
		OtherBuilder(Object type) {
			super(type);
		}
		public AbstractFormElement<?,?> buildFormElement(String name,Object value,String ctrType){
			return  new Text(name, getCname(name, ctrType), (String) value).setPlaceholder(getPlaceholder(name, ctrType));
		}
		@Override
		public AbstractLayout<?,?> buildLayoutElement(String name, Object value,
				String ctrType) {
			// TODO Auto-generated method stub
			return null;
		}
	}



}
